package com.saascloud.xxljob.core;

import com.saascloud.core.saas.SaasContextUtil;
import com.xxl.job.core.biz.model.ReturnT;
import lombok.extern.slf4j.Slf4j;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Pointcut;
import org.springframework.beans.factory.annotation.Autowired;

import java.util.Arrays;
import java.util.List;
import java.util.concurrent.CompletableFuture;
import java.util.concurrent.Executor;

/**
 * @Author: jyyou
 * @Contact: jyyou@isoftstone.com
 * @Date: 2022/6/14 9:30
 * @Version: 1.0
 * @Description:
 */
@Aspect
@Slf4j
public class XxlJobAspect {

    //从saas数据库获取租户id列表
    String[] tenantIds = {"0307f8a5b23b66b62ea689e1e36f2ae7", "0b0b56b79c295c981d935495de4dcd48"};
    List<String> tenantList = Arrays.asList(tenantIds);

    @Autowired
    private Executor executorJob;

    @Pointcut("@annotation(com.xxl.job.core.handler.annotation.XxlJob)")
    public void xxlJobCut() {
        //这里可初始化租户信息
    }

    @Around("xxlJobCut()")
    public Object around(ProceedingJoinPoint point) throws Throwable {
        Object[] args = point.getArgs();
        String className = point.getTarget().getClass().getSimpleName();
        String methodName = point.getSignature().getName();

        CompletableFuture[] futures = tenantList.stream().map(
                tenantId -> CompletableFuture.runAsync(() -> {
                            try {
                                SaasContextUtil.setTenantId(tenantId);
                                point.proceed(args);
                            } catch (Throwable throwable) {
                                log.error("job className [{}] method[{}] execute fail", className, methodName, throwable);
                            } finally {
                                SaasContextUtil.remove();
                            }
                        }
                        , executorJob)
        ).toArray(CompletableFuture[]::new);
        //阻塞等待
        CompletableFuture.allOf(futures).join();

        return ReturnT.SUCCESS;
    }

}
